home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / fog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-04  |  9.9 KB  |  369 lines

  1. /* $Id: fog.c,v 3.2 1998/03/27 03:37:40 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: fog.c,v $
  26.  * Revision 3.2  1998/03/27 03:37:40  brianp
  27.  * fixed G++ warnings
  28.  *
  29.  * Revision 3.1  1998/02/08 20:18:41  brianp
  30.  * removed unneeded headers
  31.  *
  32.  * Revision 3.0  1998/01/31 20:52:49  brianp
  33.  * initial rev
  34.  *
  35.  */
  36.  
  37.  
  38. #ifdef PC_HEADER
  39. #include "all.h"
  40. #else
  41. #include <math.h>
  42. #include <stdlib.h>
  43. #include "context.h"
  44. #include "fog.h"
  45. #include "macros.h"
  46. #include "types.h"
  47. #endif
  48.  
  49. void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
  50. {
  51.    GLenum m;
  52.  
  53.    switch (pname) {
  54.       case GL_FOG_MODE:
  55.      m = (GLenum) (GLint) *params;
  56.      if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
  57.         ctx->Fog.Mode = m;
  58.      }
  59.      else {
  60.         gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  61.      }
  62.      break;
  63.       case GL_FOG_DENSITY:
  64.      if (*params<0.0) {
  65.         gl_error( ctx, GL_INVALID_VALUE, "glFog" );
  66.      }
  67.      else {
  68.         ctx->Fog.Density = *params;
  69.      }
  70.      break;
  71.       case GL_FOG_START:
  72. #if 0
  73.      /* Prior to OpenGL 1.1, this was an error */
  74.      if (*params<0.0F) {
  75.         gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" );
  76.         return;
  77.      }
  78. #endif
  79.      ctx->Fog.Start = *params;
  80.      break;
  81.       case GL_FOG_END:
  82. #if 0
  83.      /* Prior to OpenGL 1.1, this was an error */
  84.      if (*params<0.0F) {
  85.         gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" );
  86.         return;
  87.      }
  88. #endif
  89.      ctx->Fog.End = *params;
  90.      break;
  91.       case GL_FOG_INDEX:
  92.      ctx->Fog.Index = *params;
  93.      break;
  94.       case GL_FOG_COLOR:
  95.      ctx->Fog.Color[0] = params[0];
  96.      ctx->Fog.Color[1] = params[1];
  97.      ctx->Fog.Color[2] = params[2];
  98.      ctx->Fog.Color[3] = params[3];
  99.      break;
  100.       default:
  101.      gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  102.    }
  103. }
  104.  
  105.  
  106.  
  107.  
  108. /*
  109.  * Compute the fogged color for an array of vertices.
  110.  * Input:  n - number of vertices
  111.  *         v - array of vertices
  112.  *         color - the original vertex colors
  113.  * Output:  color - the fogged colors
  114.  */
  115. void gl_fog_rgba_vertices( const GLcontext *ctx,
  116.                GLuint n, GLfloat v[][4], GLubyte color[][4] )
  117. {
  118.    GLuint i;
  119.    GLfloat d;
  120.    GLfloat rFog = ctx->Fog.Color[0] * 255.0F;
  121.    GLfloat gFog = ctx->Fog.Color[1] * 255.0F;
  122.    GLfloat bFog = ctx->Fog.Color[2] * 255.0F;
  123.    GLfloat end = ctx->Fog.End;
  124.    switch (ctx->Fog.Mode) {
  125.       case GL_LINEAR:
  126.      d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  127.      for (i=0;i<n;i++) {
  128.         GLfloat f = (end - ABSF(v[i][2])) * d;
  129.         f = CLAMP( f, 0.0F, 1.0F );
  130.         color[i][0] = (GLint) (f * color[i][0] + (1.0F-f) * rFog);
  131.         color[i][1] = (GLint) (f * color[i][1] + (1.0F-f) * gFog);
  132.         color[i][2] = (GLint) (f * color[i][2] + (1.0F-f) * bFog);
  133.      }
  134.      break;
  135.       case GL_EXP:
  136.      d = -ctx->Fog.Density;
  137.      for (i=0;i<n;i++) {
  138.         GLfloat f = exp( d * ABSF(v[i][2]) );
  139.         f = CLAMP( f, 0.0F, 1.0F );
  140.         color[i][0] = (GLint) (f * color[i][0] + (1.0F-f) * rFog);
  141.         color[i][1] = (GLint) (f * color[i][1] + (1.0F-f) * gFog);
  142.         color[i][2] = (GLint) (f * color[i][2] + (1.0F-f) * bFog);
  143.      }
  144.      break;
  145.       case GL_EXP2:
  146.      d = -(ctx->Fog.Density*ctx->Fog.Density);
  147.      for (i=0;i<n;i++) {
  148.         GLfloat z = ABSF(v[i][2]);
  149.         GLfloat f = exp( d * z*z );
  150.         f = CLAMP( f, 0.0F, 1.0F );
  151.         color[i][0] = (GLint) (f * color[i][0] + (1.0F-f) * rFog);
  152.         color[i][1] = (GLint) (f * color[i][1] + (1.0F-f) * gFog);
  153.         color[i][2] = (GLint) (f * color[i][2] + (1.0F-f) * bFog);
  154.      }
  155.      break;
  156.       default:
  157.      gl_problem(ctx, "Bad fog mode in gl_fog_rgba_vertices");
  158.      return;
  159.    }
  160. }
  161.  
  162.  
  163.  
  164. /*
  165.  * Compute the fogged color indexes for an array of vertices.
  166.  * Input:  n - number of vertices
  167.  *         v - array of vertices
  168.  * In/Out: indx - array of vertex color indexes
  169.  */
  170. void gl_fog_ci_vertices( const GLcontext *ctx,
  171.              GLuint n, GLfloat v[][4], GLuint indx[] )
  172. {
  173.    /* NOTE: the extensive use of casts generates better/faster code for MIPS */
  174.    switch (ctx->Fog.Mode) {
  175.       case GL_LINEAR:
  176.      {
  177.         GLfloat d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  178.         GLfloat fogindex = ctx->Fog.Index;
  179.         GLfloat fogend = ctx->Fog.End;
  180.         GLuint i;
  181.         for (i=0;i<n;i++) {
  182.            GLfloat f = (fogend - ABSF(v[i][2])) * d;
  183.            f = CLAMP( f, 0.0F, 1.0F );
  184.            indx[i] = (GLint)
  185.              ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  186.         }
  187.      }
  188.      break;
  189.       case GL_EXP:
  190.      {
  191.         GLfloat d = -ctx->Fog.Density;
  192.         GLfloat fogindex = ctx->Fog.Index;
  193.         GLuint i;
  194.         for (i=0;i<n;i++) {
  195.            GLfloat f = exp( d * ABSF(v[i][2]) );
  196.            f = CLAMP( f, 0.0F, 1.0F );
  197.            indx[i] = (GLint)
  198.              ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  199.         }
  200.      }
  201.      break;
  202.       case GL_EXP2:
  203.      {
  204.         GLfloat d = -(ctx->Fog.Density*ctx->Fog.Density);
  205.         GLfloat fogindex = ctx->Fog.Index;
  206.         GLuint i;
  207.         for (i=0;i<n;i++) {
  208.            GLfloat z = ABSF(v[i][2]);
  209.            GLfloat f = exp( -d * z*z );
  210.            f = CLAMP( f, 0.0F, 1.0F );
  211.            indx[i] = (GLint)
  212.              ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  213.         }
  214.      }
  215.      break;
  216.       default:
  217.      gl_problem(ctx, "Bad fog mode in gl_fog_ci_vertices");
  218.      return;
  219.    }
  220. }
  221.  
  222.  
  223.  
  224.  
  225. /*
  226.  * Apply fog to an array of RGBA pixels.
  227.  * Input:  n - number of pixels
  228.  *         z - array of integer depth values
  229.  *         red, green, blue, alpha - pixel colors
  230.  * Output:  red, green, blue, alpha - fogged pixel colors
  231.  */
  232. void gl_fog_rgba_pixels( const GLcontext *ctx,
  233.              GLuint n, const GLdepth z[], GLubyte rgba[][4] )
  234. {
  235.    GLfloat c = ctx->ProjectionMatrix[10];
  236.    GLfloat d = ctx->ProjectionMatrix[14];
  237.    GLuint i;
  238.  
  239.    GLfloat rFog = ctx->Fog.Color[0] * 255.0F;
  240.    GLfloat gFog = ctx->Fog.Color[1] * 255.0F;
  241.    GLfloat bFog = ctx->Fog.Color[2] * 255.0F;
  242.  
  243.    GLfloat tz = ctx->Viewport.Tz;
  244.    GLfloat szInv = 1.0F / ctx->Viewport.Sz;
  245.  
  246.    switch (ctx->Fog.Mode) {
  247.       case GL_LINEAR:
  248.      {
  249.         GLfloat fogEnd = ctx->Fog.End;
  250.         GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  251.         for (i=0;i<n;i++) {
  252.            GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  253.            GLfloat eyez = -d / (c+ndcz);
  254.            GLfloat f, g;
  255.            if (eyez < 0.0)  eyez = -eyez;
  256.            f = (fogEnd - eyez) * fogScale;
  257.            f = CLAMP( f, 0.0F, 1.0F );
  258.            g = 1.0F - f;
  259.            rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
  260.            rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
  261.            rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
  262.         }
  263.      }
  264.      break;
  265.       case GL_EXP:
  266.      for (i=0;i<n;i++) {
  267.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  268.         GLfloat eyez = -d / (c+ndcz);
  269.         GLfloat f, g;
  270.         if (eyez < 0.0)  eyez = -eyez;
  271.         f = exp( -ctx->Fog.Density * eyez );
  272.         f = CLAMP( f, 0.0F, 1.0F );
  273.         g = 1.0F - f;
  274.         rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
  275.         rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
  276.         rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
  277.      }
  278.      break;
  279.       case GL_EXP2:
  280.      {
  281.         GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  282.         for (i=0;i<n;i++) {
  283.            GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  284.            GLfloat eyez = -d / (c+ndcz);
  285.            GLfloat f, g;
  286.            if (eyez < 0.0)  eyez = -eyez;
  287.            f = exp( negDensitySquared * eyez*eyez );
  288.            f = CLAMP( f, 0.0F, 1.0F );
  289.            g = 1.0F - f;
  290.            rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
  291.            rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
  292.            rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
  293.         }
  294.      }
  295.      break;
  296.       default:
  297.      gl_problem(ctx, "Bad fog mode in gl_fog_rgba_pixels");
  298.      return;
  299.    }
  300. }
  301.  
  302.  
  303.  
  304.  
  305. /*
  306.  * Apply fog to an array of color index pixels.
  307.  * Input:  n - number of pixels
  308.  *         z - array of integer depth values
  309.  *         index - pixel color indexes
  310.  * Output:  index - fogged pixel color indexes
  311.  */
  312. void gl_fog_ci_pixels( const GLcontext *ctx,
  313.                GLuint n, const GLdepth z[], GLuint index[] )
  314. {
  315.    GLfloat c = ctx->ProjectionMatrix[10];
  316.    GLfloat d = ctx->ProjectionMatrix[14];
  317.    GLuint i;
  318.  
  319.    GLfloat tz = ctx->Viewport.Tz;
  320.    GLfloat szInv = 1.0F / ctx->Viewport.Sz;
  321.  
  322.    switch (ctx->Fog.Mode) {
  323.       case GL_LINEAR:
  324.      {
  325.         GLfloat fogEnd = ctx->Fog.End;
  326.         GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  327.         for (i=0;i<n;i++) {
  328.            GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  329.            GLfloat eyez = -d / (c+ndcz);
  330.            GLfloat f;
  331.            if (eyez < 0.0)  eyez = -eyez;
  332.            f = (fogEnd - eyez) * fogScale;
  333.            f = CLAMP( f, 0.0F, 1.0F );
  334.            index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  335.         }
  336.      }
  337.      break;
  338.       case GL_EXP:
  339.      for (i=0;i<n;i++) {
  340.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  341.         GLfloat eyez = -d / (c+ndcz);
  342.         GLfloat f;
  343.         if (eyez < 0.0)  eyez = -eyez;
  344.         f = exp( -ctx->Fog.Density * eyez );
  345.         f = CLAMP( f, 0.0F, 1.0F );
  346.         index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  347.      }
  348.      break;
  349.       case GL_EXP2:
  350.      {
  351.         GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  352.         for (i=0;i<n;i++) {
  353.            GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  354.            GLfloat eyez = -d / (c+ndcz);
  355.            GLfloat f;
  356.            if (eyez < 0.0)  eyez = -eyez;
  357.            f = exp( negDensitySquared * eyez*eyez );
  358.            f = CLAMP( f, 0.0F, 1.0F );
  359.            index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  360.         }
  361.      }
  362.      break;
  363.       default:
  364.      gl_problem(ctx, "Bad fog mode in gl_fog_ci_pixels");
  365.      return;
  366.    }
  367. }
  368.  
  369.